package com.presto.directo.utils

import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleOwner
import autodispose2.ObservableSubscribeProxy
import autodispose2.androidx.lifecycle.autoDispose
import com.presto.directo.base.XApplication
import com.presto.directo.entity.BaseEntity
import es.dmoral.toasty.Toasty
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import io.reactivex.rxjava3.core.Observable
import io.reactivex.rxjava3.disposables.Disposable
import io.reactivex.rxjava3.schedulers.Schedulers

typealias Success<T> = ((T?) -> Unit)?
typealias Fail = ((error: String?) -> Unit)?

fun <T : Any> Observable<T>.applySchedulers(): Observable<T> = subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())

fun <T : Any> Observable<T>.bindLifeCycle(owner: LifecycleOwner, untilEvent: Lifecycle.Event = Lifecycle.Event.ON_DESTROY): ObservableSubscribeProxy<T> {
    return autoDispose(owner, untilEvent)
}

fun <T> Observable<BaseEntity<T>>.getResult(
    owner: LifecycleOwner,
    success: Success<T> = null,
    fail: Fail = null,
    untilEvent: Lifecycle.Event = Lifecycle.Event.ON_DESTROY,
    toast: Boolean = true
) {
    autoDispose(owner, untilEvent)
        .subscribe({
            if (200 == it.code) {
                success?.invoke(it.result)
            } else {
                throw Exception(if (it.message.isNotBlank()) it.message else it.code.toString())
            }
        }, {
            fail?.invoke(it.toString())
            if (toast) {
                Toasty.error(XApplication.application, (it.message ?: "").ifEmpty { UNKNOWN_MISTAKE }).show()
            }
        })
}

fun <T : Any> Observable<T>.getResponse(
    owner: LifecycleOwner,
    success: ((T) -> Unit)? = null,
    fail: Fail = null,
    untilEvent: Lifecycle.Event = Lifecycle.Event.ON_DESTROY,
    toast: Boolean = true
) {
    autoDispose(owner, untilEvent)
        .subscribe({
            success?.invoke(it)
        }, {
            fail?.invoke(it.toString())
            if (toast) {
                Toasty.error(XApplication.application, (it.message ?: "").ifEmpty { UNKNOWN_MISTAKE }).show()
            }
        })
}

fun Disposable?.cancel() {
    if (this?.isDisposed == false) {
        dispose()
    }
}